package com.flute.icrawler.framework.framework;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

import com.flute.icrawler.app.processor.AbstractProcessor;

public class ProcessorDependency implements IProcessorDependency {
	/**
	 * 
	 */
	private static final long serialVersionUID = -8031564355010451443L;
	private List<AbstractProcessor> processorList;
	private HashMap<String, ProcessorClassList> dependencyMap;

	public ProcessorDependency() {
		this.processorList = new ArrayList<AbstractProcessor>();
		this.dependencyMap = new HashMap<String, ProcessorClassList>();
	}

	@Override
	public List<AbstractProcessor> getAllProcessors() {
		return processorList;
	}

	@Override
	/**
	 * 根据配置信息计算出除了处理过的Processor还有哪些可以处理
	 */
	public ProcessorClassList getNextProcessor(ProcessorClassList processed) {
		ProcessorClassList result = new ProcessorClassList();
		for (AbstractProcessor processor : processorList) {
			String key = getProcessorKey(processor);
			// 如果处理过的队列中没有该处理器
			if (!processed.contains(processor)) {
				// 并且该处理器有依赖关系
				// 同时和该处理器依赖的另一个处理已经执行过
				if (needDependency(key)
						&& processed
								.containsAll(getDependencyProcessorClassList(key))) {
					{
						// 加入下一个可以执行的处理器队列中
						result.addProcessor(processor);
					}
				}
				// 该处理器没有依赖关系也可加入下一个可以执行的处理器队列中
				else {
					if (!needDependency(key) && !processed.contains(processor)) {
						result.addProcessor(processor);
					}
				}
			}
		}

		return result;
	}

	private String getProcessorKey(AbstractProcessor processor) {
		return processor.getName();
	}

	/**
	 * 增加处理链 并同时增加其依赖的处理链
	 * 
	 * @param processor
	 */
	public void addProcessor(AbstractProcessor processor) {
		this.processorList.add(processor);

		StringTokenizer stringTokenizer = new StringTokenizer(
				processor.dependencyIDs, ",");

		while (stringTokenizer.hasMoreTokens()) {

			String dependencyID = stringTokenizer.nextToken();

			AbstractProcessor dependencyProcessor = getAbstractProcessor(dependencyID);

			if (null != dependencyProcessor) {
				addDependency(dependencyProcessor, processor);
			}

		}

	}

	public AbstractProcessor getAbstractProcessor(String ID) {
		for (int i = 0; i < processorList.size(); i++) {
			if (ID.equalsIgnoreCase(processorList.get(i).ID)) {
				return processorList.get(i);
			}
		}
		return null;
	}

	public void addProcessor(AbstractProcessor[] processors) {
		for (AbstractProcessor processor : processors) {
			this.processorList.add(processor);
		}
	}

	public void addDependency(AbstractProcessor front, AbstractProcessor back) {
		String key = getProcessorKey(back);
		if (!dependencyMap.containsKey(key)) {
			dependencyMap.put(key, new ProcessorClassList());
		}
		dependencyMap.get(key).addProcessor(front);
	}

	/**
	 * 判断该处理器是否需要依赖其他处理器
	 * 
	 * @param processorName
	 * @return
	 */
	public boolean needDependency(String processorName) {
		return dependencyMap.containsKey(processorName);
	}

	/**
	 * 获取该处理需要依赖的所有处理器
	 * 
	 * @param processorName
	 * @return
	 */
	public ProcessorClassList getDependencyProcessorClassList(
			String processorName) {
		return dependencyMap.get(processorName);
	}

}
